package com.yexiao.cofe.business.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yexiao.cofe.business.mapper.*;
import com.yexiao.cofe.business.pojo.*;
import com.yexiao.cofe.business.repository.OrderItemParamRepository;
import com.yexiao.cofe.business.service.OrderService;
import com.yexiao.cofe.common.exception.BusinessException;
import com.yexiao.cofe.constant.OrderConstant;
import com.yexiao.cofe.constant.ParamConstant;
import com.yexiao.cofe.proxy.RabbitMQProxy;
import com.yexiao.cofe.util.PickCodeGenerator;
import com.yexiao.cofe.util.SnowflakeIdGenerator;
import com.yexiao.cofe.util.SystemUtil;
import com.yexiao.core.util.IDateUtil;
import com.yexiao.core.util.JSONUtil;
import com.yexiao.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lkl
 * @since 2025/4/1
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private OrderItemMapper orderItemMapper;
    @Resource
    private ProductMapper productMapper;
    @Resource
    private SnowflakeIdGenerator snowflakeIdGenerator;
    @Resource
    private PickCodeGenerator pickCodeGenerator;
    @Resource
    private StoreMapper storeMapper;
    @Resource
    private ParamItemMapper paramItemMapper;
    @Resource
    private ParamValueMapper paramValueMapper;
    @Resource
    private OrderItemParamMapper orderItemParamMapper;
    @Resource
    private OrderItemParamRepository orderItemParamRepository;
    @Resource
    private RabbitMQProxy rabbitMQProxy;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject createOrder(JSONObject param, String token) {
        // 入参
        String storeId = JSONUtil.checkAndGetStr(param, "storeId");
        String remark = JSONUtil.getStr(param, "remark");
        List<JSONObject> itemListParam = JSONUtil.getList(param, JSONObject.class, "itemList");
        User user = SystemUtil.getUser(token);
        String userId = user.getUserId();

        // 合理性校验
        Store store = storeMapper.selectByStoreId(storeId);
        if(store == null) {
            throw new BusinessException("店铺不存在");
        }

        // 数据准备
        long orderId = snowflakeIdGenerator.nextId();
        List<Product> productList = storeMapper.listProduct(storeId);
        List<ParamItem> paramItemList = paramItemMapper.listAll();
        List<ParamValue> paramValueList = paramValueMapper.listAll();

        Map<Integer, Product> productMap = productList.stream().collect(Collectors.toMap(Product::getProductId, p -> p));
        Map<Integer, ParamItem> paramItemMap = paramItemList.stream().collect(Collectors.toMap(ParamItem::getId, p -> p));
        Map<Integer, ParamValue> paramValueMap = paramValueList.stream().collect(Collectors.toMap(ParamValue::getId, p -> p));

        // 创建订单
        Order order = createOrder(orderId, storeId, userId, remark);
        orderMapper.insert(order);

        // 订单项与参数
        createOrderItemParamList(orderId, itemListParam, productMap, paramItemMap, paramValueMap);

        // rabbitMQ消息队列，死信队列，用于订单超时未支付自动取消
        rabbitMQProxy.sendMessage(orderId);

        return JSONUtil.of("orderId", orderId);
    }

    /**
     * 生成订单数据
     */
    private Order createOrder(Long orderId, String storeId, String userId, String remark) {
        String now = IDateUtil.now();
        return new Order()
                .setOrderId(orderId)
                .setStoreId(storeId)
                .setUserId(userId)
                .setStatus(OrderConstant.Order_Status_Waiting_pay)
                .setHaveDel(OrderConstant.Order_Not_Del)
                .setRemark(remark)
                .setCreateTime(now)
                .setUpdateTime(now);
    }

    /**
     * 生成并插入订单项与订单项参数
     */
    private void createOrderItemParamList(long orderId,
                                          List<JSONObject> itemListParam,
                                          Map<Integer, Product> productMap,
                                          Map<Integer, ParamItem> paramItemMap,
                                          Map<Integer, ParamValue> paramValueMap) {

        for (JSONObject item : itemListParam) {
            // 入参
            List<Integer> paramValueIdList = JSONUtil.getList(item, Integer.class, "paramValueIdList");
            Integer productId = JSONUtil.checkAndGetInt(item, "productId");
            Integer quantity = JSONUtil.checkAndGetInt(item, "quantity");

            // 插入订单项并返回id
            Long orderItemId = createOrderItem(orderId, productId, quantity, productMap);

            // 插入订单项参数
            createOrderItemParam(orderItemId, paramValueIdList, paramItemMap, paramValueMap);
        }
    }

    /**
     * 生成并插入订单项
     * @return 参数项id
     */
    private Long createOrderItem(long orderId,
                                 Integer productId,
                                 Integer quantity,
                                 Map<Integer, Product> productMap) {
        // 数据
        Product product = productMap.get(productId);
        if(product == null) {
            throw new BusinessException("商品不存在");
        }

        // 订单项
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderId(orderId);
        orderItem.setProductId(productId);
        orderItem.setQuantity(quantity);
        orderItem.setPrice(product.getBasePrice());
        orderItem.setTotalPrice(product.getBasePrice().multiply(new BigDecimal(quantity)));
        orderItemMapper.insert(orderItem);

        return orderItem.getId();
    }

    /**
     * 生成并插入订单项参数
     */
    private void createOrderItemParam(long orderItemId,
                                      List<Integer> paramValueIdList,
                                      Map<Integer, ParamItem> paramItemMap,
                                      Map<Integer, ParamValue> paramValueMap) {

        // 筛选单选参数项存在多选的情况
        Set<Integer> filterItemIdSet = new HashSet<>();

        List<OrderItemParam> orderItemParamList = new ArrayList<>();
        for (Integer paramValueId : paramValueIdList) {
            // 合理性校验
            ParamValue paramValue = paramValueMap.get(paramValueId);
            if(paramValue == null) {
                throw new BusinessException("参数值不存在");
            }
            ParamItem paramItem = paramItemMap.get(paramValue.getParamItemId());
            if(paramItem == null) {
                throw new BusinessException("参数项不存在");
            }
            int itemType = paramItem.getType();
            int itemId = paramItem.getId();
            if(itemType == ParamConstant.Param_Type_Single
                    && filterItemIdSet.contains(itemId)) {
                throw new BusinessException("参数项:【" + paramItem.getName() + "】无法多选");
            }

            // 生成数据
            OrderItemParam orderItemParam = new OrderItemParam();
            orderItemParam.setOrderItemId(orderItemId);
            orderItemParam.setParamValueId(paramValueId);
            orderItemParam.setParamValueName(paramValue.getValue());
            orderItemParamList.add(orderItemParam);
            filterItemIdSet.add(itemId);
        }
        // 批量插入
        orderItemParamMapper.insert(orderItemParamList);
    }

    @Override
    public List<JSONObject> listOrder(JSONObject param, String token) {
        String storeId = JSONUtil.getStr(param, "storeId");

        List<Order> orderList;
        if(StrUtil.isNotEmpty(storeId)){
            orderList = orderMapper.listByStoreId(storeId);
        } else if(StrUtil.isNotEmpty(token)){
            User user = SystemUtil.getUser(token);
            String userId = user.getUserId();
            orderList = orderMapper.listByUserId(userId);
        } else {
            throw new BusinessException("参数缺失");
        }

        List<Long> orderIdList = orderList.stream().map(Order::getOrderId).collect(Collectors.toList());
        List<OrderItem> orderItemList = listOrderItemByOrderId(orderIdList);
        List<Integer> productIdList = orderItemList.stream().map(OrderItem::getProductId).distinct().collect(Collectors.toList());
        List<Long> orderItemIdList = orderItemList.stream().map(OrderItem::getId).collect(Collectors.toList());
        List<Product> productList = listProduct(productIdList);

        // 参数处理
        List<OrderItemParam> orderItemParamList = orderItemParamRepository.listByOrderItemIds(orderItemIdList);

        return getOrderDetail(orderList, orderItemList, productList, orderItemParamList);
    }

    @Override
    public void modifyStatus(JSONObject param) {
        Integer orderId = JSONUtil.checkAndGetInt(param, "orderId");
        Integer status = JSONUtil.checkAndGetInt(param, "status");
        String debug = JSONUtil.checkAndGetStr(param, "debug");

        // 非调试环境，进行校验
        if(StrUtil.isEmpty(debug) && checkStatusValid(status)) {
            throw new BusinessException("状态不合法");
        }

        Integer preStatus = OrderConstant.preStatusMap.get(status);
        orderMapper.modifyStatus((long) orderId, preStatus, status);
    }

    @Override
    public void pay(JSONObject param) {
        long orderId = JSONUtil.checkAndGetLong(param, "orderId");
        Order order = orderMapper.selectByOrderId(orderId);

        // 对orderId加锁，控制并发+幂等


        if(order == null) {
            throw new BusinessException("订单不存在");
        }
        if(order.getStatus() != OrderConstant.Order_Status_Waiting_pay) {
            throw new BusinessException("订单已支付");
        }

        // 修改订单状态
        orderMapper.modifyStatus(orderId,
                OrderConstant.Order_Status_Waiting_pay,
                OrderConstant.Order_Status_finish_pay);

        // 生成取餐码
        int pickCode = pickCodeGenerator.getNextCode(order.getStoreId());
        orderMapper.setPickCode(orderId, String.valueOf(pickCode));

        // websocket 推送订单数据到门店

    }

    @Override
    public void pick(JSONObject param) {
        String storeId = JSONUtil.checkAndGetStr(param, "storeId");
        String userId = JSONUtil.checkAndGetStr(param, "userId");
        int pickCode = JSONUtil.checkAndGetInt(param, "pickCode");
        long orderId = JSONUtil.checkAndGetLong(param, "orderId");

        Order order = orderMapper.selectByOrderId(orderId);
        if(StrUtil.notEquals(userId, order.getUserId())
                || StrUtil.notEquals(storeId, order.getStoreId())) {
            throw new BusinessException("门店或用户异常");
        }
        if(order.getStatus() != OrderConstant.Order_Status_Waiting_pick) {
            throw new BusinessException("不可取餐");
        }
        if(pickCode != order.getPickUpCode()) {
            throw new BusinessException("取餐码异常");
        }

        orderMapper.modifyStatus(orderId,
                OrderConstant.Order_Status_Waiting_pick,
                OrderConstant.Order_Status_finish);
    }

    @Override
    public JSONObject detail(JSONObject param, String token) {
        Long orderId = JSONUtil.checkAndGetLong(param, "orderId");
        Order order = orderMapper.selectByOrderId(orderId);
        List<OrderItem> orderItemList = orderItemMapper.listOrderItemByOrderId(orderId);
        List<Long> orderItemIdList = orderItemList.stream().map(OrderItem::getId).collect(Collectors.toList());
        List<OrderItemParam> orderItemParamList = orderItemParamRepository.listByOrderItemIds(orderItemIdList);
        List<Integer> productIdList = orderItemList.stream().map(OrderItem::getProductId).distinct().collect(Collectors.toList());
        List<Product> productList = listProduct(productIdList);
        List<JSONObject> orderDetailList = getOrderDetail(Collections.singletonList(order), orderItemList, productList, orderItemParamList);
        JSONObject res = orderDetailList.get(0);
        res.put("pickCode", order.getPickUpCode());
        return res;
    }

    @Override
    public void expire(String orderId) {
        orderMapper.modifyStatus(Long.parseLong(orderId), OrderConstant.Order_Status_Waiting_pay ,OrderConstant.Order_Status_canceled);
    }

    /**
     * 批量获取订单项
     */
    private List<OrderItem> listOrderItemByOrderId(List<Long> orderIdList) {
        List<OrderItem> orderItemList = new ArrayList<>();
        if(CollectionUtil.isEmpty(orderIdList)) {
            return orderItemList;
        }

        QueryWrapper<OrderItem> wrapper = new QueryWrapper<>();
        wrapper.in(OrderItem.ORDER_ID, orderIdList);
        orderItemList = orderItemMapper.selectList(wrapper);
        return orderItemList;
    }

    /**
     * 检查订单状态合理性
     */
    private boolean checkStatusValid(Integer status) {
        return OrderConstant.preStatusMap.containsKey(status);
    }

    /**
     * 获取订单详情
     */
    private List<JSONObject> getOrderDetail(List<Order> orderList,
                                            List<OrderItem> orderItemList,
                                            List<Product> productList,
                                            List<OrderItemParam> orderItemParamList) {
        List<JSONObject> orderDetailList = new ArrayList<>();
        BigDecimal totalPrice = BigDecimal.ZERO;

        // 订单维度
        for(Order order : orderList){
            long orderId = order.getOrderId();
            JSONObject orderDetail = Order.getBaseMsg(order);
            List<JSONObject> itemList = new ArrayList<>();

            // 订单项维度
            for (OrderItem orderItem : orderItemList) {
                if(orderItem.getOrderId() != orderId){
                    continue;
                }
                JSONObject baseMsg = OrderItem.getBaseMsg(orderItem);

                // 商品
                long productId = orderItem.getProductId();
                for (Product product : productList) {
                    if(product.getProductId() == productId){
                        baseMsg.putAll(Product.getBaseMsg(product));
                        break;
                    }
                }

                // 参数
                long orderItemId = orderItem.getId();
                List<JSONObject> paramList = new ArrayList<>();
                for (OrderItemParam param : orderItemParamList) {
                    if(orderItemId == param.getOrderItemId()){
                        paramList.add(JSONUtil.of(
                           "paramValueId", param.getParamValueId(),
                           "paramValueName",   param.getParamValueName()
                        ));
                    }
                }
                baseMsg.put("paramList", paramList);

                // 订单项数据加入订单的订单项列表
                itemList.add(baseMsg);
                totalPrice = totalPrice.add(orderItem.getTotalPrice());
            }

            if(CollectionUtil.isEmpty(itemList)) {
                log.error("订单异常，没有订单项, 订单id{}", orderId);
            }

            orderDetail.put("orderItemList", itemList);
            orderDetail.put("totalPrice", totalPrice);
            orderDetailList.add(orderDetail);
        }

        return orderDetailList;
    }

    /**
     * 批量获取商品
     */
    private List<Product> listProduct(List<Integer> productIdList) {
        List<Product> productList = new ArrayList<>();
        if(CollectionUtil.isEmpty(productIdList)) {
            return productList;
        }
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.in(Product.PRODUCT_ID, productIdList);
        productList = productMapper.selectList(wrapper);
        return productList;
    }
}
